﻿using System.Reflection;

namespace Common.Tool.ScanTool
{
    public static class ScanHelper
    {
        /// <summary>
        /// 扫描指定程序集指定的类
        /// </summary>
        /// <param name="AssemblyList"></param>
        /// <returns></returns>
        public static List<Type> ScanSpecialClassByAssemblys(List<string> AssemblyList, Func<Type, bool> Condition)
        {
            var types = new List<Type>();
            foreach (var assName in AssemblyList)
            {
                Assembly ass = Assembly.Load(assName);
                types = types.Union(ass.GetTypes()).ToList();
            }
            var scanRes = new List<Type>();
            foreach (var type in types)
            {
                if (type.IsClass && Condition(type))
                    scanRes.Add(type);
            }
            return scanRes;
        }
        /// <summary>
        /// 全扫描
        /// </summary>
        /// <param name="Condition"></param>
        /// <returns></returns>
        public static List<Type> ScanSpecialClassByAssemblys(Func<Type, bool> Condition) 
        {
            List<string> dlls = GetAllDllInBaseDir();
            if (dlls.Count == 0) return new List<Type>();
            return ScanSpecialClassByAssemblys(dlls, type => Condition(type));
        }
        /// <summary>
        /// 扫描指定公开类
        /// </summary>
        /// <param name="AssemblyList"></param>
        /// <param name="Condition"></param>
        /// <returns></returns>
        public static List<Type> ScanSpecialPublicClassByAssemblys(List<string> AssemblyList, Func<Type, bool> Condition)
        {
            return ScanSpecialClassByAssemblys(AssemblyList, type => type.IsPublic && Condition(type));
        }
        /// <summary>
        /// 全扫描
        /// </summary>
        /// <param name="Condition"></param>
        /// <returns></returns>
        public static List<Type> ScanSpecialPublicClassByAssemblys(Func<Type, bool> Condition)
        {
            List<string> dlls = GetAllDllInBaseDir();
            if (dlls.Count == 0) return new List<Type>();
            return ScanSpecialClassByAssemblys(dlls, type => type.IsPublic && Condition(type));
        }

        private static List<string> GetAllDllInBaseDir()
        {
            return Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory)
                .Where(n => n.EndsWith(".dll"))
                .Where(n => !(Path.GetFileName(n).StartsWith("System") || Path.GetFileName(n).StartsWith("Microsoft")))
                .Select(n => Path.GetFileNameWithoutExtension(n))
                .ToList();
        }
    }
}
